package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

// main 函数是程序入口点
// 演示日志双写功能的两种实现方式
func main() {
	f2() // 调用第二种实现方式（推荐）
}

// f2 函数演示日志双写的第二种实现方式（推荐）
// 使用 MultiWriteSyncer 实现同时输出到多个目标
// 这种方式更简洁，性能更好
func f2() {
	// 使用 zap 的 NewDevelopmentConfig 快速配置
	cfg := zap.NewDevelopmentConfig()
	// 替换时间格式化方式为 "年-月-日 时:分:秒"
	cfg.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")

	// 创建文件输出的 Core
	// 打开或创建日志文件，使用追加模式
	file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)

	// 创建日志核心
	// 使用 MultiWriteSyncer 同时输出到控制台和文件
	core := zapcore.NewCore(
		// 使用控制台格式编码器
		zapcore.NewConsoleEncoder(cfg.EncoderConfig),
		// 同时输出到控制台和文件
		// MultiWriteSyncer 可以同时向多个目标写入日志
		zapcore.NewMultiWriteSyncer(os.Stdout, file),
		// 设置日志级别为Info（Info及以上级别的日志会被记录）
		zapcore.InfoLevel,
	)

	// 创建一个新的 zap 日志记录器实例
	logger := zap.New(
		core,            // 使用配置好的核心组件
		zap.AddCaller(), // 启用调用者信息记录（自动添加文件名和行号）
	)
	// 使用 Info 级别记录一条日志消息
	logger.Info("xxx")
}

// f1 函数演示日志双写的第一种实现方式
// 使用 Tee 操作符合并多个 Core
// 这种方式更灵活，可以为不同目标设置不同的日志级别
func f1() {
	// 使用 zap 的 NewDevelopmentConfig 快速配置
	cfg := zap.NewDevelopmentConfig()
	// 替换时间格式化方式为 "年-月-日 时:分:秒"
	cfg.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")

	// 创建控制台输出的 Core
	// 控制台输出使用Info级别，只显示Info及以上级别的日志
	consoleCore := zapcore.NewCore(
		zapcore.NewConsoleEncoder(cfg.EncoderConfig),
		zapcore.AddSync(os.Stdout), // 输出到控制台
		zapcore.InfoLevel,          // 设置日志级别为Info
	)

	// 创建文件输出的 Core
	// 文件输出使用Debug级别，记录所有级别的日志
	file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	fileCore := zapcore.NewCore(
		zapcore.NewConsoleEncoder(cfg.EncoderConfig),
		zapcore.AddSync(file), // 输出到文件
		zapcore.DebugLevel,    // 设置日志级别为Debug（记录所有级别）
	)

	// 将控制台和文件输出合并为一个 Core
	// Tee 操作符可以将多个Core合并，日志会同时写入所有目标
	core := zapcore.NewTee(consoleCore, fileCore)

	// 创建一个新的 zap 日志记录器实例
	logger := zap.New(
		core,            // 使用合并后的核心组件
		zap.AddCaller(), // 启用调用者信息记录
	)
	// 使用 Info 级别记录一条日志消息
	logger.Info("xxx")
}
